package com.lifp.annotation.aspect;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.lifp.annotation.SysLogInfo;
import com.lifp.entity.SysLog;
import com.lifp.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @Description 自定义日志注解@SysLogInfo 切面类
 * @Author lfp
 * @Date 2022/8/25
 * @Version 1.0
 */
@Component
@Aspect
@Slf4j
public class AspectSysLogInfo {
    @Autowired
    private SysLogService logService;

    //切点，标注了自定义的注解@SysLog的方法作为切点
    @Pointcut("@annotation(com.lifp.annotation.SysLogInfo)")
    public void logPointCut(){}


    //使用环绕通知类型，保存数据
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();

        //执行方法
        Object result = point.proceed();

        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        saveSysLog(point, time);

        return result;
    }

    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
        ObjectMapper objectMapper = new ObjectMapper();

        //获取方法对象
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysLog sysLog = new SysLog();

        //获取方法标注的注解。因为切点是该注解切点，所以一定存在
        SysLogInfo syslog = method.getAnnotation(SysLogInfo.class);

        //注解上的描述,操作日志内容
        sysLog.setLogContent(syslog.value());
        sysLog.setLogType(syslog.logType());

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");

        //请求的参数
        Object[] args = joinPoint.getArgs();
        try{
            String params = objectMapper.writeValueAsString(args);
            sysLog.setRequestParam(params);
        }catch (Exception e){

        }

        //获取request
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //设置IP地址
        sysLog.setIp(request.getRemoteHost());

        //请求类型
        sysLog.setRequestUrl(request.getRequestURL().toString());

        //耗时
        sysLog.setCostTime(time);
        //保存系统日志
        logService.save(sysLog);
    }
}
